package com.za.plugin.transfer.form;

import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlSelectGroupByExpr;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;
import lombok.extern.slf4j.Slf4j;

/**
 * 跳过 group by xxx desc,xxx asc 的 desc 和 asc
 */
@Slf4j
public class SkipGroupBySortFormTransfer implements FormTransfer {
    @Override
    public boolean isSupport(String sql) {
        return sql.toLowerCase().replaceAll("\\s+group\\s+by", " group by ")
                .contains(" group by ")
                && (hasDesc(sql) || hasAsc(sql));
    }

    private static boolean hasAsc(String sql) {
        return sql.toLowerCase().replaceAll(" asc\\s*,", " asc ,").contains(" asc ");
    }

    @Override
    public String transfer(String sql) {
        return skipSortDesc(sql);
    }

    private static String skipSortDesc(String sql) {
        log.info("SkipGroupBySortFormTransfer#skipSortDesc={}",sql);
        // druid 遇到 comment 关键字会结束解析，所以这里需要特殊处理
        if (sql.toLowerCase().contains("comment")) {
            sql = sql.replaceAll("\\.comment ", ".\"comment\" ")
                    .replaceAll(",\\s*comment,", ",\"comment\",")
                    .replaceAll(",\\s*comment\\s*\\)", ",\"comment\")")
                    .replaceAll("\\s+comment\\s+", " \"comment\" ")
                    .replaceAll("(,|\\s+)comment\\s*\\.", "$1\"comment\".")
            ;
        }
        MySqlStatementParser parser = new MySqlStatementParser(sql);
        SQLStatement sqlStatement = parser.parseStatement();
        sqlStatement.accept(new MySqlASTVisitorAdapter() {
            public boolean visit(SQLSelectGroupByClause x) {
                for (SQLExpr item : x.getItems()) {
                    if (item instanceof MySqlSelectGroupByExpr) {
                        ((MySqlSelectGroupByExpr) item).setType(null);
                    }
                }
                return super.visit(x);
            }
        });
//        SQLSelectStatement sqlSelectStatement = (SQLSelectStatement) parser.parseStatement();
//        SQLSelectQuery query = sqlSelectStatement.getSelect().getQuery();
//        query.accept();
        return SQLUtils.toMySqlString(sqlStatement).toLowerCase();
    }

    public static void main(String[] args) {
        String sql = "select a.t tt from (select c.a t,c.g dd from c group by t desc having t > 0 ) a group by tt desc";
        System.out.println(skipSortDesc(sql));
    }

    private static boolean hasDesc(String sql) {
        return sql.toLowerCase().replaceAll(" desc\\s*,", " desc ,").contains(" desc ");
    }

    private boolean isSkip(String sql, int idx) {
        int j = idx - 10;
        while (j >= 0) {
            String subSql = sql.substring(j, j + 10);
            if (subSql.equalsIgnoreCase(" group by ")) {
                return true;
            } else if (subSql.equalsIgnoreCase(" order by ")) {
                return false;
            } else if (subSql.contains("select ") || subSql.contains(" where ")) {
                break;
            }
            j--;
        }
        return false;
    }
}


//        if (hasDesc(sql)) {
//            sql = sql.replaceAll(" desc,", " desc ,");
//            int idx = sql.indexOf(" desc ");
//            StringBuilder sb = new StringBuilder();
//            int left = 0;
//            while (idx >= 0) {
//                if (isSkip(sql, idx)) {
//                    sb.append(sql.substring(left, idx)).append(" ");
//                } else {
//                    sb.append(sql.substring(left, idx)).append(" desc ");
//                }
//                left = idx + 6;
//                idx = sql.indexOf(" desc ", idx + 6);
//                if (idx == -1) {
//                    sb.append(" ");
//                    if (left < sql.length()) {
//                        sb.append(sql.substring(left));
//                    }
//                }
//            }
//            sql = sb.toString();
//        }
//
//        if (hasAsc(sql)) {
//            sql = sql.replaceAll(" asc,", " asc ,");
//            int idx = sql.indexOf(" asc ");
//            StringBuilder sb = new StringBuilder();
//            int left = 0;
//            while (idx >= 0) {
//                if (isSkip(sql, idx)) {
//                    sb.append(sql.substring(left, idx)).append(" ");
//                } else {
//                    sb.append(sql.substring(left, idx)).append(" asc ");
//                }
//                left = idx + 5;
//                idx = sql.indexOf(" asc ", idx + 5);
//                if (idx == -1) {
//                    sb.append(" ");
//                    if (left < sql.length()) {
//                        sb.append(sql.substring(left));
//                    }
//                }
//            }
//            sql = sb.toString();
//        }